package top.kpromise.user.controller;

import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import top.kpromise.user.data.Config;
import top.kpromise.user.model.response.AppInfo;
import top.kpromise.user.model.response.UserInfoModel;
import top.kpromise.user.model.response.UserModel;
import top.kpromise.user.response.Result;
import top.kpromise.user.service.*;
import top.kpromise.user.utils.*;

import java.util.Date;
import java.util.Map;

@RestController
@RequestMapping("/user")
public class CreateUserController {

    private final UserService userService;
    private final UserInfoService userInfoService;
    private final AppInfoService appInfoService;
    private final UserLoginService userLoginService;
    private final VerifyCodeService verifyCodeService;
    private final KongUtils kongUtils;

    public CreateUserController(UserService userService, UserInfoService userInfoService,
                                UserLoginService userLoginService, AppInfoService appInfoService,
                                VerifyCodeService verifyCodeService, KongUtils kongUtils) {
        this.userService = userService;
        this.userInfoService = userInfoService;
        this.appInfoService = appInfoService;
        this.userLoginService = userLoginService;
        this.verifyCodeService = verifyCodeService;
        this.kongUtils = kongUtils;
    }

    private String generateUserId() {
        String id = RandomUtils.userId();
        int error = 0;
        int count = userService.getUserCountById(id);
        while (count > 0 && error < Config.MAX_CREATE_USER_ERROR_TIME) {
            id = RandomUtils.userId();
            count = userService.getUserCountById(id);
            error++;
        }
        if (error < Config.MAX_CREATE_USER_ERROR_TIME) {
            return id;
        }
        return null;
    }

    private boolean createUser(String phone, String email, String password) {
        String id = generateUserId();
        if (id != null) {
            userService.insert(id, phone, email);
            userLoginService.insert(id, Config.LoginType.PASSWORD, SecurityUtils.md5(password, Config.PASSWORD_SALT));
            saveUserInfo(phone, email, id);
            return true;
        }
        return false;
    }

    private void saveUserInfo(String phone, String email, String userId) {
        UserInfoModel userInfoModel = new UserInfoModel();
        Date now = DateUtils.currentDate();
        userInfoModel.setCreateAt(now);
        userInfoModel.setUpdateAt(now);
        userInfoModel.setUserId(userId);
        userInfoModel.setNickName("用户" + RandomUtils.verifyCode(6));
        if (RegularUtils.isEmail(email)) {
            userInfoModel.setEmail(email);
        }
        if (RegularUtils.formatPhone(phone) != null) {
            userInfoModel.setPhone(phone);
        }
        userInfoService.insert(userInfoModel);
    }

    private boolean errorAppId(String appId) {
        AppInfo appInfo = appInfoService.getByAppId(appId);
        return appInfo == null;
    }

    @RequestMapping("/create")
    @Transactional
    public Map<String, Object> createUserByPhone(String loginValue, String password,
                                                 String passwordAgain, @RequestHeader("appId") String appId) {
        if (password == null) {
            return Result.error("请输入密码");
        }
        if (password.length() != Config.passwordLen) {
            return Result.error("密码长度是" + Config.passwordLen + "位");
        }
        if (!password.equals(passwordAgain)) {
            return Result.error("两次密码输入不一致");
        }
        if (errorAppId(appId)) {
            return Result.error("AppId错误");
        }
        if (userService.getUserCountByPhone(loginValue) > 0 || userService.getUserCountByEmail(loginValue) > 0) {
            UserModel userModel = userService.findUserByLoginValue(loginValue);
            if (userModel.getEnabled() == 0) {
                return Result.error("用户已存在，请激活");
            }
            return Result.error("用户已存在，请登录");
        }
        boolean createdSuccess;
        if (RegularUtils.isEmail(loginValue)) {
            createdSuccess = createUser(loginValue, loginValue, password);
        } else {
            String phone = RegularUtils.formatPhone(loginValue);
            if (phone == null) {
                return Result.error("手机号格式错误");
            }
            createdSuccess = createUser(phone, phone, password);
        }
        if (createdSuccess) {
            userService.sendCreateUserCode(loginValue);
            return Result.data(null, "用户创建成功");
        }
        return Result.error("用户创建失败");
    }

    private Map<String, Object> checkUserActiveStatus(String loginValue, String appId) {
        if (errorAppId(appId)) {
            return Result.error("AppId错误");
        }
        UserModel userModel = userService.findUserByLoginValue(loginValue);
        if (userModel == null) {
            return Result.error("用户不存在");
        }
        if (userModel.getEnabled() == 1) {
            return Result.error("用户已激活，请登录");
        }
        return null;
    }

    @RequestMapping("/activeCode")
    @Transactional
    public Map<String, Object> activeUserCode(@RequestParam String loginValue, @RequestHeader("appId") String appId) {
        Map<String, Object> checkUserActiveStatus = checkUserActiveStatus(loginValue, appId);
        if (checkUserActiveStatus != null) {
            return checkUserActiveStatus;
        }
        if (!RegularUtils.isEmail(loginValue)) {
            return activeUserByPhone(loginValue);
        }
        return activeUserByEmail(loginValue);
    }

    private Map<String, Object> activeUserByPhone(String phone) {
        phone = RegularUtils.formatPhone(phone);
        if (phone == null) {
            return Result.error("请输入正确的手机或邮箱号");
        }
        userService.sendCreateUserCode(phone);
        return Result.data(null, "验证码已发送，请注意查收");
    }

    private Map<String, Object> activeUserByEmail(String email) {
        userService.sendCreateUserCode(email);
        return Result.data(null, "验证码已发送，请注意查收");
    }

    @RequestMapping("/active")
    @Transactional
    public Map<String, Object> activeUser(String loginValue, String verifyCode, @RequestHeader("appId") String appId) {
        Map<String, Object> checkUserActiveStatus = checkUserActiveStatus(loginValue, appId);
        if (checkUserActiveStatus != null) {
            return checkUserActiveStatus;
        }
        String userId = userService.findUserByLoginValue(loginValue).getId();
        Map<String, Object> map = verifyCodeService.checkVerifyCode(loginValue, verifyCode, Config.VerifyCodeType.createAccount);
        if (map != null) {
            return map;
        }
        userService.updateEnableByUserId(userId, 1);
        return kongUtils.loginToKong(appId, userId);
    }
}